﻿/**	lolix_inst.h
 *	----	Create Time Stamp	--2007-03-06 21:21:37--
 *------------------------------------------------------------------------------
 *	Mean	:
 *	Author	:Nick Shallery	(nicknide@gmail.com)
 *	Version	:1.0.26.38	(2009-11-11 22:16:17)
 *------------------------------------------------------------------------------
**/	/*YOU HAVE ALL LEFT WITH THIS CODE WHILE YOU KEEP COMMENT IN EVERY COPY.*/

#if			!defined(__LOLIX__LOLIX_INSTANCE__K_IN_G__)
#define		__LOLIX__LOLIX_INSTANCE__K_IN_G__
//==============================================================================
//--------------------------------------------------------------------------

#if			!defined(__LOLIX__LOLI_X_CFG__K_IN_G__)
	#include	"./lolix_cfg.h"
#endif	//	!defined(__LOLIX__LOLI_X_CFG__K_IN_G__)

#if			!defined(__LOLIX__LOLI_X_MACRO__K_IN_G__)
	#include	"./lolix_macro.h"
#endif	//	!defined(__LOLIX__LOLI_X_MACRO__K_IN_G__)
#if			!defined(__LOLIX__LOLIX_TYPE__K_IN_G__)
	#include	"./lolix_type.h"
#endif	//	!defined(__LOLIX__LOLIX_TYPE__K_IN_G__)
#if			!defined(__LOLIX__TOY__REBIND_TYPE__K_IN_G__)
	#include	"./toy/rebind_type.hpp"
#endif	//	!defined(__LOLIX__TOY__REBIND_TYPE__K_IN_G__)


namespace lolix{
	class	lolix_inst;
	class	dynamic_allocator;

	namespace sv1
	{
#pragma	pack(push, 8)
		struct	lolix_init_param
		{
			enum { _ver = 1 };
			const LOLIX_ITF_ID*	lid;
			dynamic_allocator*	alc;
			diary*				diary;
			size_type		sver	:  8;
			size_type		is_debug:  1;
			size_type		fill_z	: 23;
		};

		struct	lolix_plugin_param
		{
			enum { _ver = 1 };
			const LOLIX_ITF_ID*	lid;
			const wchar_t*		path;

			size_type	sver	:  8;
			size_type	is_debug:  1;
			size_type	u8fs	: 10;
			size_type	fill_z	: 13;
		};
#pragma	pack(pop)

		LOLIX_INLINE_CALL LOLIX_RETNV __make_lib_name_unsafe(wchar_t* buf, const LOLIX_ITF_ID* itf_id, const wchar_t* bits_string, bool is_debug)
		{	//	XXXXXXXX-YYYYYYYY-ZZZZZZZZ-WWWWWWWW-x32r.dll
			//	0123456789abcdef0123456789abcdef0123456789abc
			lx_u32 const* iid = (lx_u32 const*)itf_id;
			size_type buf_pos = ((size_type)0) - 1;
			for ( size_type i = 0; i != 4; ++i )
			{
				static const wchar_t* transform_table = L"0123456789abcdef";
				lx_u32 val = iid[i];
				for ( size_type k = 0; k != 8; ++k )
				{
					lx_u32 flag = (val>>28);
					buf[++buf_pos] = transform_table[flag & 0x0f];
					val <<= 4;
				}

				buf[++buf_pos] = '-';
			}

			buf[++buf_pos] = 'x';
			buf[++buf_pos] = bits_string[0];
			buf[++buf_pos] = bits_string[1];
			buf[++buf_pos] = is_debug?'d':'r';
			*((lx_u64*)(buf+ (++buf_pos))) = *(lx_u64*)L".dll";
			return LOLIX_RETNV_OK;
		}

	}

	typedef sv1::lolix_init_param	lolix_init_param;
	typedef sv1::lolix_plugin_param	lolix_plugin_param;

	template<size_type _Vsize, typename _Tbits>
	LOLIX_INLINE_CALL LOLIX_RETNV make_lib_name(__wchar_t (&buf)[_Vsize], size_type* start_pos, const LOLIX_ITF_ID* itf_id, const _Tbits (&bits_string)[2], bool is_debug)
	{	//	XXXXXXXX-YYYYYYYY-ZZZZZZZZ-WWWWWWWW_x32r.Wll
		const size_type min_buf_size = sizeof("XXXXXXXX-YYYYYYYY-ZZZZZZZZ-WWWWWWWW-x32r.dll");
		size_type out_size;
		if ( !start_pos )
			*(start_pos = &out_size) = 0;

		if ( _Vsize - *start_pos < min_buf_size )
			return LOLIX_ERROR_LESS_MEMORY;
		buf[*start_pos + min_buf_size-1] = 0;
		__wchar_t bits[2] = {bits_string[0], bits_string[1]};
		LOLIX_RETNV rtv;
		if ( !LOLIX_IS_ERROR(rtv = sv1::__make_lib_name_unsafe(buf + *start_pos, itf_id, bits, is_debug)) )
			*start_pos += min_buf_size - 1;
		return rtv;
	}

}


namespace lolix{
	class LOLIX_NO_VTABLE lolix_inst
		: public lolix::itf
	{
	public:
		LOLIX_DECLARE_ITF(lolix::lolix_inst, lolix::itf, (0x13f04bfe, 0x8b5f42aa, 0xbae9de08, 0x9005491e));

		class LOLIX_NO_VTABLE plugin_module
			: public lolix::itf
		{
		public:
			LOLIX_DECLARE_ITF(lolix::lolix_inst::plugin_module, lolix::itf, (0x5c25345b, 0x6b5b4ace, 0x9085320d, 0xa7639fa2));
			LOLIX_INTERFACE(unload		, LOLIX_RETNV	, (void));
		};

		LOLIX_INTERFACE(get_lolix_ver	, size_type		, (void)const);
		LOLIX_INTERFACE(get_lolix_cfg	, size_type		, (lolix_cfg* const lx_cfg, size_type lx_cfg_size)const);
		LOLIX_INTERFACE(reg_loli		, LOLIX_RETNV	, (LOLIX_ITF_ID const* in_id, itf* i));
		LOLIX_INTERFACE(unreg_loli		, LOLIX_RETNV	, (LOLIX_ITF_ID const* in_id, itf* i));

		LOLIX_INTERFACE(load			, LOLIX_RETNV	, (plugin_module** mod, lolix_plugin_param const* const plugin_param));

		template<typename _T_LOLI>
		LOLIX_INLINE_CALL	LOLIX_RETNV	reg_loli(_T_LOLI* ll)
			{
			const LOLIX_ITF_ID itf_id(LOLIX_ITF_FROM_TYPE(_T_LOLI));
			return reg_loli(&itf_id, ll);
			}
	};
}

namespace lolix{
	//\([a-zA-Z_]+[\t ]*\*[\t ]*[a-zA-Z_]+[\t ]*\)[\t ]*\(
	typedef LOLIX_RETNV	(LOLIX_CALL* fnLxLoadInst)(lolix_inst** out_ptr, const lolix_init_param* in_param);
	typedef LOLIX_RETNV	(LOLIX_CALL* fnLxFreeLib)(void);
	typedef lolix_plugin_param const*	(LOLIX_CALL* fnLxpLibInfo)(void);
	typedef LOLIX_RETNV	(LOLIX_CALL* fnLxpLoading)(lolix_inst* lx_inst);
	typedef LOLIX_RETNV	(LOLIX_CALL* fnLxpFreeing)(lolix_inst* lx_inst);
}

SYS_REGIST_TYPE(lolix::lolix_inst);
SYS_REGIST_TYPE(lolix::lolix_inst::plugin_module);

//--------------------------------------------------------------------------
//==============================================================================
#endif	//	!defined(__LOLIX__LOLIX_INSTANCE__K_IN_G__)

